/* Copyright 2009 Requirements Management System 
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.mags.remas.view;

import java.util.Date;
import java.util.List;     
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.validator.GenericValidator;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.mags.common.EngineContext;
import org.mags.remas.control.FindEntityViewController;
import org.mags.remas.logic.EntityLogic;
import org.mags.remas.model.entity.Entity;
import org.mags.remas.model.entity.EntityRelationship;
import org.mags.remas.model.entity.EntityStructure;
import org.mags.remas.view.commons.IActionMenuMaker;
import org.mags.remas.view.commons.ImageProvider;
import org.mags.remas.view.commons.TreeActionMaker;
import org.mags.remas.view.dialogs.FindRelationshipsDialog;

/**
 * 
 * @author Mario Gaitan
 *
 */
public class FindRelationshipsView extends AbstractEntityView 
	implements IActionMenuMaker {
	
	public final static String ID="org.mags.remas.view.findRelationshipsView";
	private FindEntityViewController viewController;
	private TreeActionMaker treeActionMaker;
	private FindRelationshipsDialog findDialog = new FindRelationshipsDialog(PlatformUI.getWorkbench().getDisplay());
	private Action findAction;
	private Action prevPageAction;
	private Action nextPageAction;
	private Action lastPageAction;
	private Action firstPageAction;
	private Entity root;
	
	@Override
	public void dispose() {
		super.dispose();
		findDialog.dispose();
	}
	private void makePageActions(IActionBars bars) {
		firstPageAction = new Action() {
			public void run() {
				viewController.moveFirstPage();
				getTreeViewer().refresh();
			}
		};
		firstPageAction.setText("first");
		firstPageAction.setToolTipText("first page");
		firstPageAction.setImageDescriptor(ImageProvider.getCommonImageDescriptor("first.png"));
		bars.getToolBarManager().add(firstPageAction);		
		prevPageAction = new Action() {
			public void run() {
				viewController.movePrevPage();
				getTreeViewer().refresh();
			}
		};
		prevPageAction.setText("previous");
		prevPageAction.setToolTipText("previous page");
		prevPageAction.setImageDescriptor(ImageProvider.getCommonImageDescriptor("prev.png"));
		bars.getToolBarManager().add(prevPageAction);
		nextPageAction = new Action() {
			public void run() {
				viewController.moveNextPage();
				getTreeViewer().refresh();
			}
		};
		nextPageAction.setText("next");
		nextPageAction.setToolTipText("next page");
		nextPageAction.setImageDescriptor(ImageProvider.getCommonImageDescriptor("next.png"));
		bars.getToolBarManager().add(nextPageAction);
		lastPageAction = new Action() {
			public void run() {
				viewController.moveLastPage();
				getTreeViewer().refresh();
			}
		};
		lastPageAction.setText("last");
		lastPageAction.setToolTipText("last page");
		lastPageAction.setImageDescriptor(ImageProvider.getCommonImageDescriptor("last.png"));
		bars.getToolBarManager().add(lastPageAction);				
	}
	public FindRelationshipsView() {
		super(EngineContext.getDataContext().getEntityProviderFactory().getViewTypeProvider().getLISTVIEW());
		viewController = new FindEntityViewController();
	}
	public void createPartControl(Composite parent) {
		super.createPartControl(parent);
		getTreeViewer().setContentProvider(viewController);
		getTreeViewer().setLabelProvider(viewController);
		root = new Entity();
		root.setCode("FIND");
		root.setEntityId(-1);
		root.setCreationDate(new Date());
		root.setChangeDate(new Date());
		root.setCreatedBy("");
		root.setUpdatedBy("");
		EntityRelationship rootRelationship = new EntityRelationship();
		rootRelationship.setEntity(root);
		rootRelationship.setEntityType(root.getEntityType());
		rootRelationship.setHierarchicalPath("/");		
		rootRelationship.setParent(new EntityRelationship());
		rootRelationship.getParent().setHierarchicalPath("");
		super.getTreeViewer().setRoot(rootRelationship);
		treeActionMaker = new TreeActionMaker(super.getTreeViewer(), viewController, super.getSite());
		treeActionMaker.makeActions();
		treeActionMaker.makeMenu();
		treeActionMaker.setActionMenuMaker(this);	
		IActionBars bars = getViewSite().getActionBars();
		
		findAction = new Action() {
			public void run() {
				try {		
					findDialog.show();
					viewController.setFilter(findDialog.getFilter());
					getTreeViewer().refresh();
				} catch(Exception e) {
					exceptionCatched(e);
				}
			}
		};
		findAction.setText("find");
		findAction.setToolTipText("find elements");
		findAction.setImageDescriptor(ImageProvider.getCommonImageDescriptor("find.png"));
		
		bars.getMenuManager().add(findAction);
		bars.getMenuManager().add(treeActionMaker.getEditAction());
		bars.getMenuManager().add(treeActionMaker.getDeleteAction());
		bars.getMenuManager().add(treeActionMaker.getRefreshAction());
		bars.getMenuManager().add(treeActionMaker.getSelectInViewAction());
		
		makePageActions(bars);
		bars.getToolBarManager().add(findAction);
	}
	public void makeMenuForDrop(IMenuManager manager) {
		List<EntityStructure> allowedTypes = EntityLogic.getInstance().getEntityTypeChildren(getTreeViewer().getTargetToDrop().getEntity().getEntityType());
		boolean allowedType=false;
		boolean allAllowedTypes = true;
		for(EntityRelationship j: super.getTreeViewer().getElementsDroped()) {
			allowedType=false;
			for(EntityStructure i: allowedTypes) {
				if(i.getEntityType().getEntityTypeId()==j.getEntity().getEntityType().getEntityTypeId()) {
					allowedType = true;
					break;
				}
			}
			if(allowedType) {
				if(j.getEntityParent().getEntityId()==super.getTreeViewer().getTargetToDrop().getEntity().getEntityId()
					&& j.getHierarchicalPath().startsWith(super.getTreeViewer().getTargetToDrop().getHierarchicalPath()))
					return;
				else if(super.getTreeViewer().getTargetToDrop().getHierarchicalPath().startsWith(j.getHierarchicalPath()))
					return;
			} else {
				allAllowedTypes = false;
				break;
			}
		}
		boolean allBrothers = true;
		boolean moveAbove = true;
		boolean moveBelow = true;
		List<EntityRelationship> entityRelationshipList = super.getTreeViewer().getElementsDroped();
		EntityRelationship targetToDrop = super.getTreeViewer().getTargetToDrop();
		for(EntityRelationship j: entityRelationshipList) {
			if(super.getTreeViewer().getTargetToDrop().getEntityParent()==null
				||!targetToDrop.getParent().getHierarchicalPath().equals(j.getParent().getHierarchicalPath())
				||j.getEntityParent().getEntityId()!=super.getTreeViewer().getTargetToDrop().getEntityParent().getEntityId()
				||j.getEntityRelationshipId()==super.getTreeViewer().getTargetToDrop().getEntityRelationshipId()) {
				allBrothers = false;
				if(!allAllowedTypes)
					return;
				else
					break;
			} else {
				if(moveAbove&&super.getTreeViewer().getTargetToDrop().getPosition()+1==j.getPosition()) {
					if(!moveBelow&&!allAllowedTypes)
						return;
					else
						moveAbove=false;
				}		
				if(moveBelow&&super.getTreeViewer().getTargetToDrop().getPosition()-1==j.getPosition()) {
					if(!moveAbove&&!allAllowedTypes)
						return;
					else
						moveBelow = false;
				}
			}
		}	
		if(allBrothers
			&& super.getTreeViewer().getElementsDroped().size()==1 //TEMPORAL
		) {
			if(moveAbove)
				manager.add(treeActionMaker.getMoveAboveAction());
			if(moveBelow)
				manager.add(treeActionMaker.getMoveBelowAction());
		}
		if(allAllowedTypes) {
			manager.add(new Separator());
			manager.add(treeActionMaker.getMoveAction());
			manager.add(treeActionMaker.getCopyAction());
		}
	}
	public void makeMenuForRightClick(IMenuManager manager) {
		final EntityRelationship entityRelationship = super.getTreeViewer().getSelectedElement();
		Entity entity = entityRelationship.getEntity();
		if(entity.getEntityId()>-1) {
			List<Action> actions = treeActionMaker.makeDinamicallyActions();
			if(actions!=null && actions.size()>0) {
				for(Action i: actions)
					manager.add(i);
				manager.add(new Separator());
			}
			manager.add(findAction);
			if(!GenericValidator.isBlankOrNull(entity.getEntityType().getPreviewClass()))
				manager.add(treeActionMaker.getPreviewAction());
			if(!GenericValidator.isBlankOrNull(entity.getEntityType().getProcessClass()))
				manager.add(treeActionMaker.getProcessAction());
			if(!GenericValidator.isBlankOrNull(entity.getEntityType().getEditfileClass()))
				manager.add(treeActionMaker.getEditFileAction());
			manager.add(new Separator());
			manager.add(treeActionMaker.getEditAction());
			Action delete = new Action() {
				public void run() {
					treeActionMaker.getDeleteAction().run();
					getTreeViewer().refresh();
				}
			};
			delete.setText("delete");
			delete.setToolTipText("delete select element");
			delete.setImageDescriptor(ImageProvider.getCommonImageDescriptor("delete.png"));
			manager.add(delete);
			manager.add(treeActionMaker.getRefreshAction());
			manager.add(treeActionMaker.getSelectInViewAction());
			manager.add(new Separator());
			if(root.getEntityId()!=entity.getEntityId()) {
				manager.add(treeActionMaker.getCommentsAction());
				manager.add(treeActionMaker.getAddCommentAction());
			}		
			manager.add(treeActionMaker.getPropertiesAction());
		} else {
			manager.add(findAction);
			manager.add(treeActionMaker.getRefreshAction());
			//manager.add(selectInViewAction);
			manager.add(new Separator());
			manager.add(treeActionMaker.getPropertiesAction());
		}
	}
	public boolean dragAndDrop(EntityRelationship target, List<EntityRelationship> elementsDroped) {
		treeActionMaker.getMenuDrop().setVisible(true);
		return true;
	}
	public void doubleClick(EntityRelationship first) {
		String defaultAction = first.getEntity().getEntityType().getDefaultAction();
		if(GenericValidator.isBlankOrNull(defaultAction)) 
			defaultAction = "edit";
		defaultAction = defaultAction+"Action";
		try {
			Object action = PropertyUtils.getProperty(treeActionMaker, defaultAction);
			if(action!=null&&action instanceof Action)
				((Action)action).run();
		} catch (Exception e) {
			exceptionCatched(e);
		}		
	}
	@Override
	public void keyPressed(EntityRelationship first, KeyEvent keyEvent) {
		if(keyEvent.keyCode==SWT.F2)
			super.getTreeViewer().editElement(first, 0);
		else if(keyEvent.keyCode==SWT.DEL)
			treeActionMaker.getDeleteAction().run();
		else if ((keyEvent.stateMask == SWT.CTRL) && (keyEvent.keyCode=='N'||keyEvent.keyCode=='n'))
			treeActionMaker.getMenuRightClick().setVisible(true);
	}
	@Override
	public void update(EntityRelationship entityRelationship, String property, Object value) {
		if(property.equalsIgnoreCase("name")) {
			if(entityRelationship.getEntity().getName().equals(value))
				return ;
		}
		else if(property.equalsIgnoreCase("description")) {
			if(entityRelationship.getEntity().getDescription().equals(value))
				return ;			
		}else if(property.equalsIgnoreCase("link")) {
			long oldLinkId = (entityRelationship.getLink()==null)?0:entityRelationship.getLink().getEntityRelationshipId();
			long linkId = (((EntityRelationship)value).getLink()==null)?0:((EntityRelationship)value).getLink().getEntityRelationshipId();
			if(oldLinkId==linkId)
				return ;
		}
		try {
			viewController.update(entityRelationship, property, value);
		} catch(Exception e) {
			exceptionCatched(e);
		}		
	}		
}
